#include "Channel.h"
#include "EventLoop.h"
#include <stdio.h>

Channel::Channel(EventLoop *loop, int fd)
    : _loop(loop), _fd(fd), _events(0), _revents(0)
{
}

// 1. 获取当前fd
int Channel::Fd()
{
    return _fd;
}

// 2. 获取当前fd关心的事件
uint32_t Channel::Events()
{
    return _events;
}

// 3. 设置就绪事件
void Channel::SetREvents(uint32_t events)
{
    _revents = events;
}

// 4. 向Channel对象注册各类事件的处理函数
void Channel::SetReadCallback(const EventCallback &cb)
{
    _read_callback = cb;
}
void Channel::SetWriteCallback(const EventCallback &cb)
{
    _write_callback = cb;
}
void Channel::SetCloseCallback(const EventCallback &cb)
{
    _close_callback = cb;
}
void Channel::SetErrorCallback(const EventCallback &cb)
{
    _error_callback = cb;
}
void Channel::SetEventCallback(const EventCallback &cb)
{
    _event_callback = cb;
}

// 5. 当前是否监控可读事件
bool Channel::ReadAble()
{
    return (_events & EPOLLIN);
}

// 6. 当前是否监控可写事件
bool Channel::WriteAble()
{
    return (_events & EPOLLOUT);
}

// 7. 启动可读事件监控
void Channel::EnableRead()
{
    _events |= EPOLLIN;
    Updata();
}

// 8. 启动可写事件监控
void Channel::EnableWrite()
{
    _events |= EPOLLOUT;
    Updata();
}

// 9. 关闭读事件监控
void Channel::DisableRead()
{
    _events &= ~EPOLLIN;
    Updata();
}

// 10. 关闭写事件监控
void Channel::DisableWrite()
{
    _events &= ~EPOLLOUT;
    Updata();
}

// 11. 关闭所有事件监控
void Channel::DisableAll()
{
    _events &= 0;
}

// 12. 移除监控
void Channel::Remove()
{
    return _loop->RemoveEvent(this);
}

// 13. 更新事件监控
void Channel::Updata()
{
    return _loop->UpdataEvent(this);
}

// 14. 事件处理，一旦连接触发了事件，就调用这个函数，自己触发了什么事件如何处理自己决定
void Channel::HandleEvent()
{
    // EPOLLIN: 可读  EPOLLOUT：可写  EPOLLRDHUP：对端关闭连接或半关闭  EPOLLPRI：有紧急数据可读 EPOLLERR：文件描述符发生错误
    // EPOLLHUP: 挂断事件（连接完全关闭，需清理资源）
    if ((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI))
    {
        if (_event_callback)
            _event_callback();
        if (_read_callback)
            _read_callback();
    }
    // 有可能会释放连接的操作事件，一次只处理一个
    if (_revents & EPOLLOUT)
    {
        if (_event_callback)
            _event_callback();
        if (_write_callback)
            _write_callback();
    }
    else if (_revents & EPOLLERR)
    {
        if (_event_callback)
            _event_callback();
        if (_error_callback)
            _error_callback();
    }
    else if (_revents & EPOLLHUP)
    {
        if (_event_callback)
            _event_callback();
        if (_close_callback)
            _close_callback();
    }
}